package com.xjuse.yida.commom.redis;

import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.redisson.api.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;

import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Stream;

/**
 * @author 杜文旭
 * @describe: Redisson分布式缓存
 */
@Component
@Slf4j
public class RedissonCacheTemplate {

    @Autowired
    private RedissonClient redissonClient;

    /**
     * 缓存实时数据
     *
     * @param dynamicId
     * @param data
     */
    public void cacheRealtimeDataWithSerialize(String dynamicId, Object data) {
        cacheWithSerialize(dynamicId, data, 5, TimeUnit.SECONDS);
    }

    /**
     * 缓存非实时数据
     *
     * @param dynamicId
     * @param data
     */
    public void cacheNoRealtimeDataWithSerialize(String dynamicId, Object data) {
        cacheWithSerialize(dynamicId, data, 7, TimeUnit.DAYS);
    }

    /**
     * 缓存实时数据
     *
     * @param dynamicId
     * @param data
     */
    public void cacheRealtimeDataNoSerialize(String dynamicId, String data) {
        cacheAsObjectById(dynamicId, data, 5, TimeUnit.SECONDS);
    }

    /**
     * 缓存非实时数据
     *
     * @param dynamicId
     * @param data
     */
    public void cacheNoRealtimeDataNoSerialize(String dynamicId, Object data) {
        cacheAsObjectById(dynamicId, data, 7, TimeUnit.DAYS);
    }

    /**
     * 缓存要推送的数据
     *
     * @param dynamicId
     * @param data
     */
    public void cacheWithSerialize(String dynamicId, Object data, @Nullable Integer expired, @Nullable TimeUnit timeUnit) {
        if (null == dynamicId || "".equals(dynamicId) || ObjectUtils.isEmpty(data)) {
            log.error("Cache push data encounter illegal parameter: {}, {}", dynamicId, data);
            return;
        }

        String json = null;
        try {
            json = JSONUtil.toJsonStr(data);
        } catch (Exception e) {
            log.error("Serialize data to json error: {}", data, e);
        }

        if (null == json || "".equals(json)) {
            log.error("Cache push data encounter null data: {}", data);
            return;
        }

        RBucket<Object> bucket = redissonClient.getBucket(dynamicId);
        if (expired == null || timeUnit == null) {
            bucket.set(json);
        } else {
            bucket.set(json, expired, timeUnit);
        }
    }

    /**
     * 缓存要推送的数据
     *
     * @param dynamicId
     * @param data
     */
    public void cacheAsObjectById(String dynamicId, Object data, @Nullable Integer expired, @Nullable TimeUnit timeUnit) {
        if (null == dynamicId || "".equals(dynamicId) || ObjectUtils.isEmpty(data)) {
            log.error("Cache push data encounter illegal parameter: {}, {}", dynamicId, data);
            return;
        }

        RBucket<Object> bucket = redissonClient.getBucket(dynamicId);
        if (expired == null || timeUnit == null) {
            bucket.set(data);
        } else {
            bucket.set(data, expired, timeUnit);
        }
    }

    /**
     * 删除单个key值
     *
     * @param key key
     * @return 删除的value
     */
    public String keyRemove(String key) {
        if (StringUtils.isNotBlank(key)) {
            RBucket<String> bucket = redissonClient.getBucket(key);
            if (bucket.isExists()){
                return bucket.getAndDelete();
            }
        }
        return null;
    }


    /**
     * Hash 结构存储数据
     *
     * @param mapKey    HASH key
     * @param dynamicId hash 内层key
     * @param data      存储的内容
     *                  //     * @param expired   过期时间
     *                  //     * @param timeUnit  过期时间单位
     */
    public void hashCacheWithSerialize(String mapKey, String dynamicId, Object data) {
        if (StringUtils.isBlank(mapKey) || StringUtils.isBlank(dynamicId) || ObjectUtils.isEmpty(data)) {
            log.error("DistributedDataCache hashCacheWithSerialize encounter illegal parameter: mapKey= {}, dynamicId = {}，data={}", mapKey, dynamicId, data);
            return;
        }

        String json = null;
        try {
            json = JSONUtil.toJsonStr(data);
        } catch (Exception e) {
            log.error("Serialize data to json error: {}", data, e);
        }

        if (StringUtils.isBlank(json)) {
            log.error("Cache push data encounter null data: {}", data);
            return;
        }
        redissonClient.getMap(mapKey).put(dynamicId, json);
    }

    /**
     * Hash 结构存储数据
     *
     * @param mapKey    HASH key
     * @param dynamicId hash 内层key
     * @param data      存储的内容
     *                  //     * @param expired   过期时间
     *                  //     * @param timeUnit  过期时间单位
     */
    public void hashCacheNoSerialize(String mapKey, String dynamicId, String data) {
        if (StringUtils.isBlank(mapKey) || StringUtils.isBlank(dynamicId) || null == data) {
            log.error("DistributedDataCache hashCacheWithSerialize encounter illegal parameter: mapKey= {}, dynamicId = {}，data={}", mapKey, dynamicId, data);
            return;
        }
        redissonClient.getMap(mapKey).put(dynamicId, data);
    }

    /**
     * 获取 hash结构数据
     *
     * @param mapKey
     * @return
     */
    public Map<String,String> hashGet(String mapKey) {
        if (StringUtils.isBlank(mapKey)) {
            log.error("DistributedDataCache hashGetById encounter illegal parameter: mapKey= {}", mapKey);
        }
        RMap<String, String> map = redissonClient.getMap(mapKey);
        if (map.isExists()) {
            return map;
        } else {
            return null;
        }
    }

    /**
     * 删除指定Map 键值
     *
     * @param mapKey   map key
     * @param cacheKey key
     */
    public void hashRemove(String mapKey, String cacheKey) {
        if (StringUtils.isNotBlank(mapKey) && StringUtils.isNotBlank(cacheKey)) {
            RMap<Object, Object> map = redissonClient.getMap(mapKey);
            if (map.isExists()) {
                map.remove(cacheKey);
            }
        }
    }

    /**
     * list push (Object)
     *
     * @param cacheKey
     * @param data
     */
    public void pushList(String cacheKey, Object data) {
        String json = null;
        try {
            json = JSONUtil.toJsonStr(data);
        } catch (Exception e) {
            log.error("pushList serialize data to json error: {}", data, e);
        }

        if (StringUtils.isNoneBlank(json)) {
            RList<String> list = redissonClient.getList(cacheKey);
            list.add(json);
        }
    }

    /**
     * 获取指定 Pattern的 key
     *
     * @param pattern key pattern
     * @return
     */
    public Stream<String> keys(String pattern) {
        if (StringUtils.isNotBlank(pattern)) {
            RKeys keys = redissonClient.getKeys();
            return keys.getKeysStreamByPattern(pattern);
        } else {
            return null;
        }
    }
}